package rad.framework.security.encryption;

import org.apache.commons.lang.StringUtils;

/**
 * Obfuscation encryptor. 
 * 
 * @author Chunyun Zhao
 */
public class ObfEncryptor implements Encryptor {
    private final static String ENCRYPTION_PREFIX = "{OBF}";
     
    private final int SEED1 = 357;
    private final int SEED2 = 555;
    private final int SEED3 = 36;

    /* 
     * Encrypts the data. It doesn't encrypt the data if it is already encrypted.
     */    
    public String encrypt(String clearData) {
        if ( StringUtils.isEmpty(clearData) || clearData.startsWith(ENCRYPTION_PREFIX)) {
            return clearData;
        }
        StringBuffer buf = new StringBuffer();
        buf.append(ENCRYPTION_PREFIX);
        byte[] b = clearData.getBytes();
 
        for (int i = 0; i < b.length; i++) {
            byte b1 = b[i];
            byte b2 = b[clearData.length() - (i + 1)];
            int i1 = SEED1 + b1 + b2;
            int i2 = SEED1 + b1 - b2;
            int i0 = i1 * SEED2 + i2;
            String x = Integer.toString(i0, SEED3);
 
            switch (x.length()) {
            case 1:
            case 2:
            case 3:
                buf.append('0');
            default:
                buf.append(x);
            }
        }
        return buf.toString();
    }
 
    /* 
     * Decrypts the data. It doesn't decrypt the data if it is not encrypted.
     */        
    public String decrypt(String obfuscatedData) {
        if ( StringUtils.isEmpty(obfuscatedData) || !obfuscatedData.startsWith(ENCRYPTION_PREFIX)) {
            return obfuscatedData;
        }
        obfuscatedData = obfuscatedData.substring(ENCRYPTION_PREFIX.length());
         
        byte[] b = new byte[obfuscatedData.length() / 2];
        int l = 0;
        for (int i = 0; i < obfuscatedData.length(); i += 4) {
            String x = obfuscatedData.substring(i, i + 4);
            int i0 = Integer.parseInt(x, SEED3);
            int i1 = (i0 / SEED2);
            int i2 = (i0 % SEED2);
            b[l++] = (byte) ((i1 + i2 - SEED1 * 2) / 2);
        }
 
        return new String(b, 0, l);
    }
 
}

